#pragma once

#include "Types.h"
#include "Container.h"
#include "ScrollBox.h"
#include "Range.h"
#include "Timer.h"

namespace My {

class Row;
class List;

/**
 * Control that represents a row in a list control
 */
class Row : 
	public virtual Control,
	protected RangeItem
{
	friend class List;
public:
	Row();
public:
	My::Size GetRowHeight() const
		{ return RangeItem::GetSize(); }
	My::Size GetIndex() const
		{ return m_Index; }
	virtual bool Visible() const
		{ return m_Visible; }
	virtual CRect Bounds() const;
	/// If not visible, returns -1
	int GetVisibleIndex() const;
protected:
	List * GetList() const
		{ return m_pList; }
	void SetVisible(bool);
	void SetRowHeight(My::Size);
	virtual void BoundsChanged();
private:
	My::Size CalcVisibleIndex() const;
private:
	List *	m_pList;
	int		m_Index;
	bool	m_Visible;
};

class List : 
	public virtual Control,
	protected Container,
	protected Range
{
	friend class Row;
public:
	List(ScrollBox &);
public:
	bool IsEmpty() const;
	My::Size GetRowCount() const;
	Row & GetRow(My::Size) const;
	My::Size GetVisibleRowCount() const;
	Row & GetVisibleRow(My::Size) const;
	My::Size GetTotalHeight() const;
	void Append(Row * pRow) 
		{ Insert(GetRowCount(), &pRow, 1); }
	void Insert(My::Size pos, Row * pRow)
		{ Insert(pos, &pRow, 1); }
	void Insert(My::Size pos, Row * rows[], My::Size count);
	void Remove(My::Size pos, My::Size count = 1);
	void Clear();
public:
	virtual CRect Bounds() const;
	virtual void ProcessEvent(My::Event &);
	virtual void HandlePaint(CDC * pDC, const CRect & r);
public:
	int VisibleRowIndexAt(int y);
	virtual Control * GetHoverControl(CPoint);
	virtual void Paint(CDC *, const CRect &);
	virtual void InvalidateSpan(Span);
	virtual void SizeChanged();
	virtual int GetOffset() const;
	virtual void OnScroll(CPoint);
	virtual My::Size GetContentWidth() const	
		{ return 0; }
	virtual My::Size GetContentHeight() const;
	virtual void UpdateContentSize();
	void SetAutoScroll(int);
	void OnAutoScroll(bool mouseMove);
private:
	void SetRowVisible(Row &, bool);
protected:
	Timer				m_AutoScroll;
	ScrollBox &			m_Box;
	std::vector<Row *>	m_Rows;
	int					m_YAutoScroll;
	int					m_ScrollLine;
};

class ListBoxWidget : 
	public ScrollBox, 
	public Widget {
public:
	ListBoxWidget() : m_List(* this) { }
public:
	virtual CRect Bounds() const
		{ return Widget::Bounds(); }
	virtual bool Visible() const
		{ return Widget::Visible(); }
	virtual const CFont * Font() const
		{ return Widget::Font(); }
public:
	List & GetList()
		{ return m_List; }
private:
	List	m_List;
};

} // My